home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / vm / vmServer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-19  |  11.8 KB  |  462 lines

  1. /* vmServer.c -
  2.  *
  3.  *         This file contains routines that read and write pages to/from the page
  4.  *    server and file server.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/vm/vmServer.c,v 9.8 92/04/10 16:46:08 kupfer Exp $ SPRITE (Berkeley)";
  12. #endif not lint
  13.  
  14. #include <sprite.h>
  15. #include <vm.h>
  16. #include <vmInt.h>
  17. #include <vmSwapDir.h>
  18. #include <lock.h>
  19. #include <status.h>
  20. #include <sched.h>
  21. #include <sync.h>
  22. #include <dbg.h>
  23. #include <list.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <proc.h>
  27. #include <stdio.h>
  28.  
  29. Boolean    vmUseFSReadAhead = TRUE;
  30. extern    Boolean    vm_NoStickySegments;
  31. char        *sprintf();
  32.  
  33. /*
  34.  * Condition to wait on when want to do a swap file operation but someone
  35.  * is already doing one.  This is used for synchronization of opening
  36.  * of swap files.  It is possible that the open of the swap file could
  37.  * happen more than once if the open is not synchronized.
  38.  */
  39. Sync_Condition    swapFileCondition;
  40.  
  41. void    Fscache_BlocksUnneeded();
  42.  
  43.  
  44. /*
  45.  *----------------------------------------------------------------------
  46.  *
  47.  * VmSwapFileLock --
  48.  *
  49.  *    Set a lock on the swap file for the given segment.  If the lock
  50.  *    is already set then wait.
  51.  *
  52.  * Results:
  53.  *    None.
  54.  *
  55.  * Side effects:
  56.  *    Flags field in segment table entry is modified to make the segment
  57.  *    locked.
  58.  *----------------------------------------------------------------------
  59.  */
  60.  
  61. ENTRY void
  62. VmSwapFileLock(segPtr)
  63.     register    Vm_Segment    *segPtr;
  64. {
  65.     LOCK_MONITOR;
  66.  
  67.     while (segPtr->flags & VM_SWAP_FILE_LOCKED) {
  68.     (void) Sync_Wait(&swapFileCondition, FALSE);
  69.     }
  70.     segPtr->flags |= VM_SWAP_FILE_LOCKED;
  71.  
  72.     UNLOCK_MONITOR;
  73. }
  74.  
  75.  
  76. /*
  77.  *----------------------------------------------------------------------
  78.  *
  79.  * VmSwapFileUnlock --
  80.  *
  81.  *    Clear the lock on the swap file for the given segment.
  82.  *
  83.  * Results:
  84.  *    None.
  85.  *
  86.  * Side effects:
  87.  *    Flags field in segment table entry is modified to make the segment
  88.  *    unlocked and anyone waiting for the segment is awakened.
  89.  *----------------------------------------------------------------------
  90.  */
  91.  
  92. ENTRY void
  93. VmSwapFileUnlock(segPtr)
  94.     register    Vm_Segment    *segPtr;
  95. {
  96.     LOCK_MONITOR;
  97.  
  98.     segPtr->flags &= ~VM_SWAP_FILE_LOCKED;
  99.     Sync_Broadcast(&swapFileCondition);
  100.  
  101.     UNLOCK_MONITOR;
  102. }
  103.  
  104. /*
  105.  *----------------------------------------------------------------------
  106.  *
  107.  * VmPageServerRead --
  108.  *
  109.  *    Read the given page from the swap file into the given page frame.
  110.  *    This routine will panic if the swap file does not exist.
  111.  *
  112.  *    NOTE: It is assumed that the page frame that is to be written into
  113.  *          cannot be given to another segment.
  114.  *
  115.  * Results:
  116.  *    SUCCESS if the page server could be read from or an error if either
  117.  *    a swap file could not be opened or the page server could not be
  118.  *    read from the swap file.
  119.  *
  120.  * Side effects:
  121.  *    The hardware page is written into.
  122.  *
  123.  *----------------------------------------------------------------------
  124.  */
  125. ReturnStatus
  126. VmPageServerRead(virtAddrPtr, pageFrame)
  127.     Vm_VirtAddr            *virtAddrPtr;
  128.     unsigned    int        pageFrame;
  129. {
  130.     register    int        mappedAddr;
  131.     register    Vm_Segment    *segPtr;
  132.     int                status;
  133.     int                pageToRead;
  134.  
  135.     segPtr = virtAddrPtr->segPtr;
  136.     if (!(segPtr->flags & VM_SWAP_FILE_OPENED)) {
  137.     printf("VmPageServerRead: swap file %s doesn't exist.\n",
  138.            (segPtr->swapFileName != (char *)NIL
  139.         ? segPtr->swapFileName : "???"));
  140.     return(VM_SWAP_ERROR);
  141.     }
  142.  
  143.     if (segPtr->type == VM_STACK) {
  144.     pageToRead = mach_LastUserStackPage - virtAddrPtr->page;
  145.     } else if (segPtr->type == VM_SHARED) {
  146.     pageToRead= virtAddrPtr->page - segOffset(virtAddrPtr) +
  147.         (virtAddrPtr->sharedPtr->fileAddr>>vmPageShift);
  148.     } else {
  149.     pageToRead = virtAddrPtr->page - segPtr->offset;
  150.     }
  151.  
  152.     /*
  153.      * Map the page into the kernel's address space and fill it from the
  154.      * file server.
  155.      */
  156.     mappedAddr = (int) VmMapPage(pageFrame);
  157.     status = Fs_PageRead(segPtr->swapFilePtr, (Address) mappedAddr,
  158.              pageToRead << vmPageShift, vm_PageSize, FS_SWAP_PAGE);
  159.     VmUnmapPage((Address) mappedAddr);
  160.  
  161.     return(status);
  162. }
  163.  
  164.  
  165.  
  166. /*
  167.  *----------------------------------------------------------------------
  168.  *
  169.  * VmPageServerWrite --
  170.  *
  171.  *    Write the given page frame to the swap file.  If the swap file is
  172.  *    not open yet then it will be open.
  173.  *
  174.  *    NOTE: It is assumed that the page frame that is to be read from
  175.  *          cannot be given to another segment.
  176.  *
  177.  * Results:
  178.  *    SUCCESS if the page server could be written to or an error if either
  179.  *    a swap file could not be opened or the page server could not be
  180.  *    written to.
  181.  *
  182.  * Side effects:
  183.  *    If no swap file exists, then one is created.
  184.  *
  185.  *----------------------------------------------------------------------
  186.  */
  187. ReturnStatus
  188. VmPageServerWrite(virtAddrPtr, pageFrame, toDisk)
  189.     Vm_VirtAddr        *virtAddrPtr;
  190.     unsigned int    pageFrame;
  191.     Boolean        toDisk;
  192. {
  193.     register    int        mappedAddr;
  194.     register    Vm_Segment    *segPtr;
  195.     ReturnStatus        status;
  196.     int                pageToWrite;
  197.  
  198.     vmStat.pagesWritten++;
  199.  
  200.     segPtr = virtAddrPtr->segPtr;
  201.  
  202.     /*
  203.      * Lock the swap file while opening it so that we don't have more than
  204.      * one swap file open at a time.
  205.      */
  206.     VmSwapFileLock(segPtr);
  207.     if (!(segPtr->flags & VM_SWAP_FILE_OPENED)) {
  208.     status = VmOpenSwapFile(segPtr);
  209.     if (status != SUCCESS) {
  210.         VmSwapFileUnlock(segPtr);
  211.         return(status);
  212.     }
  213.     }
  214.     VmSwapFileUnlock(segPtr);
  215.  
  216.     if (segPtr->type == VM_STACK) {
  217.     pageToWrite = mach_LastUserStackPage - virtAddrPtr->page;
  218.     } else {
  219.     pageToWrite = virtAddrPtr->page - segOffset(virtAddrPtr);
  220.     }
  221.  
  222.     /*
  223.      * Map the page into the kernel's address space and write it out.
  224.      */
  225.     VmMach_FlushPage(virtAddrPtr, FALSE);
  226.     mappedAddr = (int) VmMapPage(pageFrame);
  227.     status = Fs_PageWrite(segPtr->swapFilePtr, (Address) mappedAddr,
  228.               pageToWrite << vmPageShift, vm_PageSize, toDisk);
  229.     VmUnmapPage((Address) mappedAddr);
  230.  
  231.     return(status);
  232. }
  233.  
  234.  
  235. /*
  236.  *----------------------------------------------------------------------
  237.  *
  238.  * VmCopySwapSpace --
  239.  *
  240.  *    Copy the swap space for all pages that have been written out to swap
  241.  *    space for the source segment into the destination segments swap space.
  242.  *
  243.  * Results:
  244.  *    Error if swap file could not be opened, read or written.  Otherwise
  245.  *    SUCCESS is returned.
  246.  *
  247.  * Side effects:
  248.  *    None.
  249.  *
  250.  *----------------------------------------------------------------------
  251.  */
  252.  
  253. ReturnStatus
  254. VmCopySwapSpace(srcSegPtr, destSegPtr)
  255.     register    Vm_Segment    *srcSegPtr;
  256.     register    Vm_Segment    *destSegPtr;
  257. {
  258.     register    int    page;
  259.     register    Vm_PTE    *ptePtr;
  260.     ReturnStatus    status = SUCCESS;
  261.     register    int    i;
  262.  
  263.     VmSwapFileLock(srcSegPtr);
  264.     if (!(srcSegPtr->flags & VM_SWAP_FILE_OPENED)) {
  265.     VmSwapFileUnlock(srcSegPtr);
  266.     return(SUCCESS);
  267.     }
  268.     VmSwapFileUnlock(srcSegPtr);
  269.  
  270.     VmSwapFileLock(destSegPtr);
  271.     if (!(destSegPtr->flags & VM_SWAP_FILE_OPENED)) {
  272.     status = VmOpenSwapFile(destSegPtr);
  273.     if (status != SUCCESS) {
  274.         VmSwapFileUnlock(destSegPtr);
  275.         return(status);
  276.     }
  277.     }
  278.     VmSwapFileUnlock(destSegPtr);
  279.  
  280.     if (destSegPtr->type == VM_STACK) {
  281.     page = destSegPtr->numPages - 1;
  282.     ptePtr = VmGetPTEPtr(destSegPtr, mach_LastUserStackPage - 
  283.                              destSegPtr->numPages + 1);
  284.     } else {
  285.     page = 0;
  286.         ptePtr = destSegPtr->ptPtr;
  287.     }
  288.  
  289.     for (i = 0; i < destSegPtr->numPages; i++, VmIncPTEPtr(ptePtr, 1)) {
  290.  
  291.     if (*ptePtr & VM_IN_PROGRESS_BIT) {
  292.         *ptePtr &= ~VM_IN_PROGRESS_BIT;
  293.         /*
  294.          * The page is on the swap file and not in memory.  Need to copy
  295.          * the page in the file.
  296.          */
  297.         vmStat.swapPagesCopied++;
  298.         status = Fs_PageCopy(srcSegPtr->swapFilePtr, 
  299.                 destSegPtr->swapFilePtr, 
  300.                 page << vmPageShift, vm_PageSize);
  301.         if (status != SUCCESS) {
  302.         break;
  303.         }
  304.     }
  305.     if (destSegPtr->type == VM_STACK) {
  306.         page--;
  307.     } else {
  308.         page++;
  309.     }
  310.     }
  311.  
  312.     return(status);
  313. }
  314.  
  315.  
  316. /*
  317.  *----------------------------------------------------------------------
  318.  *
  319.  * VmFileServerRead --
  320.  *
  321.  *    Read the given page from the file server into the given page frame.
  322.  *
  323.  *    NOTE: It is assumed that the page frame that is to be written into
  324.  *          cannot be given to another segment.
  325.  *
  326.  * Results:
  327.  *    Error if file server could not be read from, SUCCESS otherwise.
  328.  *
  329.  * Side effects:
  330.  *    The hardware page is written into.
  331.  *
  332.  *----------------------------------------------------------------------
  333.  */
  334.  
  335. ReturnStatus
  336. VmFileServerRead(virtAddrPtr, pageFrame)
  337.     Vm_VirtAddr        *virtAddrPtr;
  338.     unsigned int    pageFrame;
  339. {
  340.     register    int        mappedAddr;
  341.     register    Vm_Segment    *segPtr;
  342.     int                length;
  343.     int                status;
  344.     int                offset;
  345.  
  346.     segPtr = virtAddrPtr->segPtr;
  347.  
  348.     /*
  349.      * Map the page frame into the kernel's address space.
  350.      */
  351.     mappedAddr = (int) VmMapPage(pageFrame);
  352.     /*
  353.      * The address to read is just the page offset into the segment
  354.      * ((page - offset) << vmPageShift) plus the offset of this segment into
  355.      * the file (fileAddr).
  356.      * (We have to use the right offset for shared memory.
  357.      */
  358.     length = vm_PageSize;
  359.     if (segPtr->type == VM_SHARED) {
  360.     if (virtAddrPtr->sharedPtr == (Vm_SegProcList *)NIL) {
  361.         printf("*** NIL sharedPtr in VmFileServerRead\n");
  362.         return FAILURE;
  363.     }
  364.     offset = ((virtAddrPtr->page - segOffset(virtAddrPtr)) << vmPageShift)
  365.         + virtAddrPtr->sharedPtr->fileAddr;
  366.     } else {
  367.     offset = ((virtAddrPtr->page - segOffset(virtAddrPtr)) << vmPageShift)
  368.         + segPtr->fileAddr;
  369.     }
  370.     if (vmPrefetch || !vmUseFSReadAhead) {
  371.     /*
  372.      * If we are using prefetch then do the reads ourselves.
  373.      */
  374.     if (segPtr->type == VM_CODE && !vm_NoStickySegments) {
  375.         status = Fs_PageRead(segPtr->filePtr, (Address)mappedAddr, offset,
  376.                  length, FS_CODE_PAGE);
  377.     } else {
  378.         status = Fs_PageRead(segPtr->filePtr, (Address)mappedAddr, offset,
  379.                  length, FS_HEAP_PAGE);
  380.     }
  381.     } else {
  382.     /*
  383.      * No prefetch so use the file system full blown mechanism so
  384.      * that we can take advantage of its read ahead.
  385.      */
  386.     status = Fs_Read(segPtr->filePtr, (Address) mappedAddr, offset,
  387.              &length);
  388.     if (status == SUCCESS && !vm_NoStickySegments && 
  389.         segPtr->type == VM_CODE) {
  390.         /*
  391.          * Tell the file system that we just read some file system blocks
  392.          * into virtual memory.
  393.          */
  394.         Fscache_BlocksUnneeded(segPtr->filePtr, offset, vm_PageSize, TRUE);
  395.     }
  396.     }
  397.     VmUnmapPage((Address) mappedAddr);
  398.     if (status != SUCCESS) {
  399.     printf("%s VmFileServerRead: Error %x from Fs_Read or Fs_PageRead\n",
  400.         "Warning:", status);
  401.     return(status);
  402.     }
  403.  
  404.     return(SUCCESS);
  405. }
  406.  
  407.  
  408.  
  409. /*
  410.  *----------------------------------------------------------------------
  411.  *
  412.  * VmCopySwapPage --
  413.  *
  414.  *    Copy the swap page from the source segment's swap file to the
  415.  *    destination.
  416.  *
  417.  * Results:
  418.  *    Error if swap file could not be opened, read or written.  Otherwise
  419.  *    SUCCESS is returned.
  420.  *
  421.  * Side effects:
  422.  *    None.
  423.  *
  424.  *----------------------------------------------------------------------
  425.  */
  426. ReturnStatus
  427. VmCopySwapPage(srcSegPtr, virtPage, destSegPtr)
  428.     register    Vm_Segment    *srcSegPtr;    /* Source for swap file. */
  429.     int                virtPage;    /* Virtual page to copy. */
  430.     register    Vm_Segment    *destSegPtr;    /* Destination swap file. */
  431. {
  432.     int            pageToCopy;
  433.     ReturnStatus    status;
  434.  
  435.     /*
  436.      * Lock the swap file while opening it so that we don't have more than
  437.      * one swap file open at a time.
  438.      */
  439.     VmSwapFileLock(destSegPtr);
  440.     if (!(destSegPtr->flags & VM_SWAP_FILE_OPENED)) {
  441.     status = VmOpenSwapFile(destSegPtr);
  442.     if (status != SUCCESS) {
  443.         VmSwapFileUnlock(destSegPtr);
  444.         return(status);
  445.     }
  446.     }
  447.     VmSwapFileUnlock(destSegPtr);
  448.  
  449.     vmStat.swapPagesCopied++;
  450.     if (destSegPtr->type == VM_STACK) {
  451.     pageToCopy = mach_LastUserStackPage - virtPage;
  452.     } else {
  453.     pageToCopy = virtPage - destSegPtr->offset;
  454.     }
  455.  
  456.     status = Fs_PageCopy(srcSegPtr->swapFilePtr, 
  457.              destSegPtr->swapFilePtr, 
  458.              pageToCopy << vmPageShift, vm_PageSize);
  459.  
  460.     return(status);
  461. }
  462.